
package com.studiofortress.sf.audio;

/**
 * This is not intended to be directly used, instead it offers general buffering
 * functionality for playing music from a given AudioStream. Sub-classes of this
 * class should add the MP3, Ogg or WAV specific functionality by passing up an
 * AudioInputStream.
 *
 * If you want audio, look at the other audio players first before looking at
 * this one.
 * 
 * @author Joseph Lenton - JosephLenton@StudioFortress.com
 */
public class BufferedAudioPlayer implements AudioPlayer
{
    private final AudioStreamFactory audioFactory;
    private final InnerAudioPlayer player;
    
    BufferedAudioPlayer(AudioStreamFactory audioFactory)
    {
        if (audioFactory == null) {
            throw new IllegalArgumentException("The given audioInput cannot be null.");
        }

        this.audioFactory = audioFactory;
        
        player = new InnerAudioPlayer( audioFactory );
        player.start();
    }

    /**
     * Creates a new audio player which uses the same data source as the given
     * audioPlayer. It will play independantly of the given audioPlayer, but
     * because it shares the same audio data internally it will use less memory
     * then an entirely new instance of the original player.
     *
     * Essentially it's a new audio player except it'll use the same ogg or wav
     * data inside to massively save on space.
     * 
     * @param audioPlayer
     */
    public BufferedAudioPlayer(BufferedAudioPlayer audioPlayer)
    {
        this( audioPlayer.getAudioFactory() );
    }
    
    /**
     * The AudioFactory defines how to create AudioInputStreams which are used
     * for playing the music.
     * @return The AudioFactory this uses for creating it's AudioInputStreams.
     */
    protected AudioStreamFactory getAudioFactory()
    {
        return audioFactory;
    }

    /**
     * Creates and returns an alternate BufferAduioPlayer that copies the one
     * given.
     * @return Another BufferedAudioPlayer which can play the same sound effects as this one.
     */
    @Override
    public BufferedAudioPlayer clone()
    {
        return new BufferedAudioPlayer( this );
    }

    /**
     * @return The InnerAudioPlayer used by this class to pass the sound to the speakers.
     */
    InnerAudioPlayer getPlayer()
    {
        return player;
    }

    /**
     * Starts playing sound.
     */
    public void play()
    {
        player.play();
    }

    /**
     * @return True if this is currently playing, otherwise false.
     */
    public boolean isPlaying()
    {
        return player.isPlaying();
    }

    /**
     * Stops the sound from playing and returns to the beginning of the audio.
     */
    public void stop()
    {
        player.stopPlaying();
    }

    /**
     * @return True if this is in a stopped state, otherwise false.
     */
    public boolean isStopped()
    {
        return !player.isPlaying() && !player.isPaused();
    }

    /**
     * Pauses the currently playing music which can be restarted by calling
     * play().
     */
    public void pause()
    {
        player.pause();
    }

    /**
     * @return True if this is currently paused, otherwise false.
     */
    public boolean isPaused()
    {
        return player.isPaused();
    }

    /**
     * Sets if this should be repeating it's audio or not when it gets to the
     * end.
     * @param repeat True if it should replay it's audio when it reaches the end, otherwise false.
     */
    public void setRepeat(boolean repeat)
    {
        player.setAudioRepeating( repeat );
    }

    /**
     * @return True if this will repeat it's audio when it reaches the end of it's audio.
     */
    public boolean isRepeating()
    {
        return player.isAudioRepeating();
    }

    /**
     * The volume to use, between 0 and 100, for the audio.
     * @param volume The volume for the audio to play at.
     */
    public void setVolume(int volume)
    {
        player.setVolume( volume );
    }

    /**
     * @return The volume for this audio that is currently playing, between 0 and 100.
     */
    public int getVolume()
    {
        return player.getVolume();
    }
}
